﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using HCFramework.API.LINQ;

namespace C
{
    public class ProductCategoryController
    {
        public static List<ProductCategory> ListCategoryCache = GetAll();

        private static List<ProductCategory> GetAll()
        {
            HCDataContext db = new HCDataContext();
            return db.ProductCategories.ToList();
        }

        public static void Insert(ProductCategory a)
        {
            HCDataContext db = new HCDataContext();
            db.ProductCategories.InsertOnSubmit(a);
            db.SubmitChanges();

            ListCategoryCache = GetAll();
        }

        public static void Update(ProductCategory a, HCDataContext db)
        {
            if (a.ParentID.HasValue && IsParentChild(a.ProductCategoryID, a.ParentID.Value))
                throw new Exception("Không thể đổi chỗ vị trí giữa 2 node này.");

            db.SubmitChanges();

            ListCategoryCache = GetAll();
        }

        public static void Delete(int id)
        {
            HCDataContext db = new HCDataContext();
            ProductCategory a = db.ProductCategories.Where(
                ik => ik.ProductCategoryID == id).First();

            if (a.ProductCategories.Count > 0) throw new Exception("Không thể xóa vì vẫn còn category con");
            if (a.ProductProperties.Count > 0) throw new Exception("Không thể xóa vì vẫn còn ProductProperties");
            if (a.Products.Count > 0) throw new Exception("Không thể xóa vì vẫn còn Products");

            db.ProductCategories.DeleteOnSubmit(a);
            db.SubmitChanges();

            ListCategoryCache = GetAll();
        }

        public static ProductCategory GetByID(int id, HCDataContext db)
        {
            return db.ProductCategories.Where(
                ik => ik.ProductCategoryID == id).FirstOrDefault();
        }

        public static ProductCategory GetByID(int id)
        {
            return GetByID(id, new HCDataContext());
        }

        /// <summary>
        /// Trả về tất cả các node con, cháu,... (Không tính node hiện tại)
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        public static List<ProductCategory> GetAllChild(ProductCategory category)
        {
            List<ProductCategory> ret = new List<ProductCategory>();
            foreach (ProductCategory child in category.ProductCategories.ToList())
            {
                ret.Add(child);
                ret.AddRange(GetAllChild(child));
            }
            return ret;
        }

        /// <summary>
        /// Trả về tất cả các node cha, ông,... (Không tính node hiện tại)
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        public static List<ProductCategory> GetAllParent(ProductCategory category)
        {
            List<ProductCategory> ret = new List<ProductCategory>();
            if (category.ProductCategory1 != null)
            {
                ret.Add(category.ProductCategory1);
                ret.AddRange(GetAllParent(category.ProductCategory1));
            }
            return ret;
        }

        /// <summary>
        /// Tra ve node cha o cap do cao nhat, tinh ca node hien tai
        /// </summary>
        /// <param name="categoryId"></param>
        /// <returns></returns>
        public static ProductCategory GetRootCategory(int categoryId)
        {
            ProductCategory cat = GetByID(categoryId);
            ProductCategory root = GetAllParent(cat).LastOrDefault();
            if (root != null) return root;
            else return cat;
        }

        /// <summary>
        /// Trả về tất cả các node lá con, cháu, ..., tính cả node hiện tại (nếu node hiện tại là lá)
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        public static List<ProductCategory> GetAllLeaf(ProductCategory category)
        {
            List<ProductCategory> ret = new List<ProductCategory>();
            if (category.ProductCategories.Count < 1)
            {
                ret.Add(category);
                return ret;
            }
            else
            {
                ret.AddRange(GetAllChild(category).Where(ik => ik.ProductCategories.Count < 1));
                return ret;
            }
        }

        /// <summary>
        /// Trả về true nếu 2 node có quan hệ cha con, ông cháu... Hoặc 2 node trùng nhau
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="child"></param>
        /// <returns></returns>
        public static bool IsParentChild(ProductCategory parent, ProductCategory child)
        {
            if (parent.ProductCategoryID == child.ProductCategoryID) return true;
            if (GetAllParent(child).Select(ik => ik.ProductCategoryID).Contains(parent.ProductCategoryID)) return true;
            return false;
        }

        /// <summary>
        /// Trả về true nếu 2 node có quan hệ cha con, ông cháu... Hoặc 2 node trùng nhau
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="child"></param>
        /// <returns></returns>
        public static bool IsParentChild(int parentID, int childID)
        {
            ProductCategory parent = GetByID(parentID);
            ProductCategory child = GetByID(childID);

            return IsParentChild(parent, child);
        }

        public static bool IsLeafNode(int id)
        {
            return GetByID(id).ProductCategories.Count < 1;
        }

        public static bool HasProperty(int id)
        {
            return GetByID(id).ProductProperties.Count > 0;
        }

        /// <summary>
        /// Vi du tra ve: "Noi that/Tranh ve/Tranh dong que"
        /// </summary>
        /// <param name="catID"></param>
        /// <returns></returns>
        public static string GetPathName(int catID)
        {
            string ret = "";
            ProductCategory cat = GetByID(catID);
            while (cat != null)
            {
                ret = cat.Name + "/" + ret;
                cat = cat.ProductCategory1;
            }
            return ret.TrimEnd('/');
        }
    }
}